import { _decorator, Component, Node } from 'cc';
import { EventConst } from '../../../common/Common';
import { App } from '../../../App';
const { ccclass, property } = _decorator;

import { GameTrainAI } from './GameTrainAI';
import { GameTrainUser } from './GameTrainUser';
import { Cue } from '../Cue';
import { find } from 'cc';
import { Ball } from '../Ball';
import { GameModel2 } from './GameModel2';
import { GameLayer2 } from './GameLayer2';
import { js } from 'cc';
import UtilTool from '../../../tools/UtilTool';
import { showTip } from '../../../tools/PopuUp';
import { Vec3 } from 'cc';
import { tween } from 'cc';
import GameUtils2 from './GameUtils2';
import { BelognBallType, HIT_BALL_TIME, POS_BALL_TIME, TrainLayer, TrainTimeType } from './GameConstant2';
import { Tween } from 'cc';
import { random } from 'cc';
import { formatTime } from '../../../../../extensions/build_game_auto/@types/packages/scene/@types/cce/3d/manager/scene/scene-cache';
import { Role } from '../Role';
import { GameBaseModel } from '../GameBaseModel';
import { RigidBody } from 'cc';
import { BLACK_BALL, GameManage, WHITE_BALL } from '../GameManage';
import { TrainPlayBase } from './TrainPlayBase';
import { GameBaseLogic, GameEndState, GamePlayState, GamePlayTip } from '../GameBaseLogic';
import { instantiate } from 'cc';
import { ComboNode } from '../ComboNode';
import { Vec2 } from 'cc';


export class GameTrainLogic extends GameBaseLogic {

    ai : GameTrainAI | null = null
    mine : GameTrainUser | null = null

    gameView : GameModel2 = null
    gameLayer : GameLayer2 = null

    reset() {
        
        this.stopAllAction()

        if(this.ai) {
            this.ai.reset()
        }
        if(this.mine) {
            this.mine.reset()
        }
        this.ballInRoleList = []
        this.isHasSetBallBelogn = false
        this.curPlayState = GamePlayState.NONE
        this.beforePlayState = GamePlayState.NONE
        this.contactBallList = []
        this.comboCount = 0
        this.gameEndState = GameEndState.NONE

        let allBallList = App.Model.gameManage.otherBallArr.concat(this.whiteBallCtrl.node)
        allBallList.forEach((ball)=>{
            ball.getComponent(Ball).reset()
        })

        this.gameView.posBallCtrl.reset()

        this.ballInRoleList.length = 0
        this.contactBallList.length = 0
        this.curComboClearBallList.length = 0

        this.ai = null
        this.mine = null
        this.curPlayUser = null
        
    }

    // 停止全部动作
    stopAllAction() {
        if(this.ai) {
            Tween.stopAllByTarget(this.ai)
        }
        if(this.mine) {
            Tween.stopAllByTarget(this.mine)
        }
        this.gameView.cueCtrl.stopAllAction()
        Tween.stopAllByTarget(this)
        Tween.stopAllByTarget(this.gameView.posBallCtrl)
        Tween.stopAllByTarget(this.gameView.posBallCtrl.node)
    }



    exitGame() {
        this.stopAllAction()
        this.gameLayer.stopTimeSchedule()
        this.gameView.removeAllEvent()
    }

    startGame() {

        this.gameView = App.Model.gameView as GameModel2
        this.gameLayer = this.gameView.gameLayerCtrl


        // this.test(false)
        // this.test(true)

        // this.test2()

        // return
        
        this.initGame()

    }

    // 重新开始
    restart() {
        this.initGame()
    }

    initGame() {

        this.reset()
        // this.gameView.resetAllBallPos(false)
        this.gameView.resetAllBallPos(true)

         // TODO 错开时间，因为resetBallPos会发生EventConst.ALLBALL_SLEEP事件
        this.gameView.removeAllEvent()

        UtilTool.printLog("test initGame1")

        this.ai = new GameTrainAI(this)
        this.mine = new GameTrainUser(this)

        this.gameLayer.showWhoAction(0)

        this.gameLayer.setUserName(this.mine.getName(), this.ai.getName())

        this.updateBallInfo()
        
        tween(this).delay(0.5).call(()=>{
            
            this.gameView.initEvent()
            UtilTool.printLog("test initGame2")
            this.setPlayState(GamePlayState.GAME_START)
            this.showPlayTip(GamePlayTip.GAME_START)
            
            this.setActionTime(TrainTimeType.TIME_HIT)
            
            // this.initTest()


        }).start()

    }

    // 游戏开始，随机决定开球方
    onGameStart() {
        
        // let random = Math.random()
        // if (random > 0.5) {
        //     this.curPlayUser = this.ai
        // } else {
        //     this.curPlayUser = this.mine
        // }
        // this.curPlayUser = this.ai // 默认玩家开始
        this.curPlayUser = this.mine // 默认玩家开始
        this.isHasSetBallBelogn = false

        if(this.isAiPlay()) {
            this.gameLayer.showWhoAction(2)
        } else {
            this.gameLayer.showWhoAction(1)
        }
        
        this.setPlayState(GamePlayState.WAIT_HIT_BALL)
    }
    // 等待击球
    onWaitHitBall() {
        this.contactBallList.length = 0
        this.ballInRoleList.length = 0
        this.roleInballList.length = 0
        this.curPlayUser.onCue()
        this.setActionTime(TrainTimeType.TIME_HIT)
    }

    // 击球
    onHitBall() {
        this.setAbelBall(false)
    }

    // 设置呼吸效果
    setAbelBall(show=false) {
        // 处理自己所属球节点的呼吸效果
        if (show) {
            if (this.curPlayUser == this.mine) {
                for (let i = 0; i < App.Model.gameManage.otherBallArr.length; i++) {
                    const ball = App.Model.gameManage.otherBallArr[i]
                    if (ball) {
                        let ballObj = ball.getComponent(Ball)
                        if (this.curPlayUser.isBelognMine(ballObj.number)) {
                            ballObj.setAbelNode(true)
                        }
                        else{
                            ballObj.setAbelNode(false)
                        }
                    }
                }
            }
        }
        else{
            // if (this.curPlayUser == this.mine) {
                for (let i = 0; i < App.Model.gameManage.otherBallArr.length; i++) {
                    const ball = App.Model.gameManage.otherBallArr[i]
                    if (ball) {
                        let ballObj = ball.getComponent(Ball)
                        ballObj.setAbelNode(false)
                    }
                }
            // }
        }
        
    }

    // 击球结束
    onHitBallEnd() {

        GameUtils2.printBallPos()

        // 是否当前回合设置了归属球
        let isCurRoundSetBelogn = false

        // 花球列表，不含白球和黑球的球列表
        let colorBallList = this.ballInRoleList.filter(ballNumber=>{
            return ballNumber != BLACK_BALL && ballNumber != WHITE_BALL
        })

        let endState = this.checkGameEndState()
        if(endState != GameEndState.NONE) {
            this.gameEndState = endState
            this.setPlayState(GamePlayState.GAME_END)
            return
        }

        // 分球处理
        if(!this.isHasSetBallBelogn) {

            let isCurPlayAi = this.isAiPlay()

            // 有球进洞, 进的第一个球（不含白球和黑球）就是归属球
            if(this.ballInRoleList.length > 0) { 

                if(colorBallList.length > 0) {

                    let minBallList = [1,2,3,4,5,6,7]
                    let maxBallList = [9,10,11,12,13,14,15]
    
                    let ballNumber = colorBallList[0]
    
                    if(ballNumber > BLACK_BALL) { // 大球进洞
                        this.ai.ballList = isCurPlayAi ? maxBallList : minBallList
                        this.mine.ballList = isCurPlayAi ? minBallList : maxBallList

                        this.ai.allBallList = this.ai.ballList
                        this.mine.allBallList = this.mine.ballList

                        this.ai.ballType = isCurPlayAi ? BelognBallType.BIG : BelognBallType.SMALL
                        this.mine.ballType = isCurPlayAi ? BelognBallType.SMALL : BelognBallType.BIG

                    } else { // 小球进洞
                        this.ai.ballList = isCurPlayAi ? minBallList : maxBallList
                        this.mine.ballList = isCurPlayAi ? maxBallList : minBallList

                        this.ai.allBallList = this.ai.ballList
                        this.mine.allBallList = this.mine.ballList

                        this.ai.ballType = isCurPlayAi ? BelognBallType.SMALL : BelognBallType.BIG
                        this.mine.ballType = isCurPlayAi ? BelognBallType.BIG : BelognBallType.SMALL
                    }
                    
                    this.isHasSetBallBelogn = true

                    this.updateBallInfo()

                    isCurRoundSetBelogn = true

                    this.showPlayTip(GamePlayTip.COLOR_SET)
                }


            } else {

            }

        }


        // 犯规处理
        let foulType = this.checkIsFoul(isCurRoundSetBelogn)

        // 是否有击球方所属的球进
        let beloinBallInList = colorBallList.filter(ballNumber=>{
            return this.curPlayUser.isBelognMine(ballNumber)
        })

        // 进球处理
        this.handleBallInRole()

        if(foulType>0) {
            this.changePlay()
            this.showPlayTip(GamePlayTip.FOUL_CHANGE)
            this.setPlayState(GamePlayState.WAIT_POS_BALL)
            return
        }

        if(beloinBallInList.length > 0) {
            // 属于连杠，继续打
            this.comboCount += 1
            UtilTool.printLog("cur play state ", this.getName(), "连杆数", this.comboCount)

            // 把打进的球加到combo列表
            this.ballInRoleList.forEach((ballNumber)=>{
                this.curComboClearBallList.push(ballNumber)
            })
            
            if(!isCurRoundSetBelogn) { // 会与选定花球的提示冲突
                this.showPlayTip(GamePlayTip.COMB, this.comboCount)
            }

            this.setPlayState(GamePlayState.WAIT_HIT_BALL)

            // 处理自己所属球节点的呼吸效果
            if (this.curPlayUser == this.mine) {
                this.setAbelBall(true)
            }

            // 重置作用点
            if (this.gameView.cueCtrl.isMine) {
                this.gameLayer.setActionPoint(new Vec2(0,0))
            }     
        } else {
            // 换人打
            this.setPlayState(GamePlayState.ONE_ROUND_END)
        }

    }

    // 处理进洞的球，那个球进了，就加谁的分数
    handleBallInRole() {
        this.ballInRoleList.forEach(ballNumber=>{
            this.ai.removeBall(ballNumber)
            this.mine.removeBall(ballNumber)
        })

        // 已经分过球了
        if(this.isHasSetBallBelogn) {

            // 如果己方的球都打完了，那就把黑球加进去
            if(this.ai.ballList.length == 0) {
                this.ai.ballList.push(BLACK_BALL)
            }
            if(this.mine.ballList.length == 0) {
                this.mine.ballList.push(BLACK_BALL)
            }
        }
    }

    // 更新UI上的球的信息
    updateBallInfo() {

        if(!this.isHasSetBallBelogn) {
            this.gameLayer.updateBallInfo([], [])
            return
        }

        // 已经分过球的情况
        let mineBallList = []
        let aiBallList = []
        let minList = [1,2,3,4,5,6,7]
        let maxList = [9,10,11,12,13,14,15]
        if(this.mine.ballType == BelognBallType.BIG) {
            mineBallList = maxList
            aiBallList = minList
        } else {
            mineBallList = minList
            aiBallList = maxList
        }

        // 根据当前球是否隐藏，来更新球的信息
        let otherBallList = App.Model.gameManage.otherBallArr
        otherBallList.forEach((ball)=>{
            if(!ball.active) {
                let number = ball.getComponent(Ball).number

                let index = mineBallList.indexOf(number)
                if(index != -1) {
                    mineBallList.splice(index, 1)
                }
    
                let index2 = aiBallList.indexOf(number)
                if(index2 != -1) {
                    aiBallList.splice(index2, 1)
                }
            }
        })

        // 没有黑球进球的情况
        let blackBall = (App.Model.gameView as GameBaseModel).getBallByNumber(BLACK_BALL)
        if(blackBall.node.active) {
            // 如果己方的球都打完了，那就把黑球加进去
            if(mineBallList.length == 0) {
                mineBallList.push(BLACK_BALL)
            }
            if(aiBallList.length == 0) {
                aiBallList.push(BLACK_BALL)
            }
        }

        this.gameLayer.updateBallInfo(mineBallList, aiBallList)
    }

    // 收到倒计时时间结束事件
    downTimeEndEvent() {
        if (this.gameLayer.node==null) return
        
        switch(this.curPlayState) {
            case GamePlayState.HIT_BALL: // 不处理
                this.stopActionTime()
                return

            case GamePlayState.WAIT_HIT_BALL: // 在等待击球时，还没击球，属于犯规，交换选手摆球
                // 
                this.changePlay()
                this.setPlayState(GamePlayState.WAIT_POS_BALL)
                return

            case GamePlayState.WAIT_POS_BALL: // 在等待摆球时，还没摆球，属于犯规，交换选手摆球
                this.changePlay()
                this.setPlayState(GamePlayState.WAIT_POS_BALL)
                return
        }

        console.error("cur downTimeEndEvent play state is unhandle", this.curPlayState)

    }

    // 判断游戏是否结束
    checkGameEndState() : GameEndState {

        /** 输局
         *  A.选手分属的一组球未全部击入袋之前，就打进黑8。
            B.击落己方目标球同时，带进黑"8"。
            C.在击打"8"号球时，母球落袋或和黑"8"同时落袋。

        *   abc简化为：黑球进洞的情况：
        *   (1) 只有一个球进洞，而且我的球只剩下黑球了，则为赢
        *   (2) 2个及以上的球进洞，只要有自己所属的球进洞或者母球进洞，则为输
        */
        let isBlackInRole = this.ballInRoleList.includes(BLACK_BALL)
        
        // 根据当前玩的人的输赢情况，获取当前玩家的输赢状态
        let getCurPlayIsWinState = (isWin) =>{
            if(this.isAiPlay()) {
                return isWin ? GameEndState.FAIL : GameEndState.WIN
            } else {
                return isWin ? GameEndState.WIN : GameEndState.FAIL
            }
        }

        if(isBlackInRole) { // 黑球进洞的情况

            if(!this.isHasSetBallBelogn) { // 还没分球的情况
                return getCurPlayIsWinState(false)
            }

            // 只有一个球进洞，而且我的球只剩下黑球了，则为赢
            if(this.ballInRoleList.length == 1) {
                if(this.curPlayUser.ballList.length == 1) { // 只有一个球的情况
                    let isBlack = this.curPlayUser.ballList[0] == BLACK_BALL
                    if(isBlack) { 
                        UtilTool.printLog("cur end 1")
                        if(!this.isHasSetBallBelogn) { // 还没分球的情况
                            return getCurPlayIsWinState(false)
                        } else {
                            return getCurPlayIsWinState(true)
                        }
                    } else {
                        UtilTool.printLog("cur end 2")
                        return getCurPlayIsWinState(false)
                    }
                } else {
                    UtilTool.printLog("cur end 3")
                    return getCurPlayIsWinState(false)
                }
            } else { // 2个及以上的球进洞

                // 有母球进洞的情况
                let isWhiteInRole = this.ballInRoleList.includes(0)
                if(isWhiteInRole) {
                    UtilTool.printLog("cur end 4")
                    return getCurPlayIsWinState(false) 
                }

                // 还有其他的球
                let isHasBall = this.curPlayUser.ballList.length > 0 && this.curPlayUser.ballList[0] != BLACK_BALL
                if(isHasBall) {
                    UtilTool.printLog("cur end 5")
                    return getCurPlayIsWinState(false)
                } else {
                    // 该种情况，就是我的球也打完了，但在击打黑球进洞时，也把对面的球打进洞了，这种情况也算赢
                    UtilTool.printLog("cur end 6")
                    return getCurPlayIsWinState(true)
                }
            }
        }

        return GameEndState.NONE
    }

    // 是否ai玩
    isAiPlay() {
        return this.curPlayUser == this.ai
    }

    // 等待摆球
    onWaitPosBall() {
        this.gameView.whiteBall.getComponent(Ball).hide()
        this.curPlayUser.posWhiteBall()
        this.setActionTime(TrainTimeType.TIME_POS)
    }

    // 摆球结束
    onPosBallEnd() {
        this.setPlayState(GamePlayState.WAIT_HIT_BALL)
    }

    // 切换玩家
    changePlay() {
        this.comboCount = 0
        this.curComboClearBallList.length = 0

        // 重置作用点
        if (this.gameView.cueCtrl.isMine) {
            this.gameLayer.setActionPoint(new Vec2(0,0))
        }        

        if(this.curPlayUser == this.ai) {
            this.curPlayUser = this.mine
            this.gameLayer.showWhoAction(1)
        } else {
            this.curPlayUser = this.ai
            this.gameLayer.showWhoAction(2)
        }

        // 处理自己所属球节点的呼吸效果
        this.setAbelBall(this.curPlayUser == this.mine)

    }

    // 一轮结束
    onOneRoundEnd() {
        this.changePlay()
        this.showPlayTip(GamePlayTip.NORMAL_CHANGE)
        this.setPlayState(GamePlayState.WAIT_HIT_BALL)
    }

    // 游戏结束
    onGameEnd() {
        
        this.gameLayer.stopActionTime()
        this.gameLayer.showWhoAction(0)

        // 判断是否是一杆清台
        let isAllOneClear = true
        let minList = [1,2,3,4,5,6,7,8]
        let maxList = [8,9,10,11,12,13,14,15]

        let ballType = (this.curPlayUser as TrainPlayBase).ballType

        let needClearList = ballType == BelognBallType.BIG ? maxList : minList
        for(let i=0; i<needClearList.length; i++) {
            let ballNumber = needClearList[i]
            if(!this.curComboClearBallList.includes(ballNumber)) {
                isAllOneClear = false
                break
            }
        }
        if(isAllOneClear) {
            (App.Model.gameView as GameBaseModel).showAllOneClear()
        }

        let delayTime = 0.5
        if(isAllOneClear) {
            delayTime = 2.5
        }

        if(this.gameEndState == GameEndState.FAIL) {
        
            tween(this).delay(delayTime).call(()=>{                
                UtilTool.printLog("cur play 游戏结束，你输了")
                GameUtils2.showLayer(TrainLayer.FAIL)
            }).start()

        } else if(this.gameEndState == GameEndState.WIN) {
            
            tween(this).delay(delayTime).call(()=>{
                UtilTool.printLog("cur play 游戏结束，你赢了")
                GameUtils2.showLayer(TrainLayer.WIN)
            }).start()
            
        }

        // this.showPlayTip(GamePlayTip.GAME_END)
    }
    
    getName() : String{
        if(this.curPlayUser == null) {
            return "待定"
        }
        return this.curPlayUser.getName()
    }

    // 设置操作时间
    setActionTime(timeType : TrainTimeType) {
        switch(timeType) {
            case TrainTimeType.TIME_HIT:
                this.gameLayer.setActionTime(HIT_BALL_TIME)
                break
            case TrainTimeType.TIME_POS:
                this.gameLayer.setActionTime(POS_BALL_TIME)
                break
        }
    }

    stopActionTime() {
        this.gameLayer.stopActionTime()
    }

    showCombo() {
        (App.Model.gameView as GameBaseModel).showCombo(this.comboCount)
    }
    

    test2() {

        this.ai = new GameTrainAI(this)

        let otherBallArr = App.Model.gameManage.otherBallArr

        // let targetBall = null

        // otherBallArr.forEach((ball)=>{
        //     let number = ball.getComponent(Ball).number
        //     if(number != 1) {
        //         ball.getComponent(Ball).hide()
        //     } else {
        //         targetBall = ball
        //     }
        // })

        // targetBall.worldPosition = new Vec3(76.301, targetBall.worldPosition.y,49.562)
        
        this.whiteBallCtrl.node.worldPosition = new Vec3(-22.902, this.whiteBallCtrl.node.worldPosition.y, 74.832)

        // this.ai.onTestCue()


        
        // this.ai.hitTargetBallAngle(targetBall)
    }

    initTest() {

        let whiteBall = this.gameView.whiteBall
        let blackBall = (App.Model.gameView as GameBaseModel).getBallByNumber(BLACK_BALL)


        blackBall.node.worldPosition = new Vec3(-24.858, blackBall.node.worldPosition.y, -61.139)

        whiteBall.worldPosition = new Vec3(-24.858, whiteBall.worldPosition.y, -46.574)

        // tween(this).delay(2).call(()=>{
        //     whiteBall.getComponent(RigidBody).applyLocalForce(new Vec3(0,0,-2000), new Vec3(0,0,0))
        // }).start()


    }

}
